package com.wxsm.wechat.core.rest;

import com.wxsm.wechat.core.exception.ServiceException;
import com.wxsm.wechat.util.JsonUtil;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Created with Yang Huan
 * Date: 2017/3/2
 * Time: 11:34
 */
@Component
public class MyRestClientImpl implements MyRestClient {

    private static RestTemplate restTemplate;

    public MyRestClientImpl() {
        restTemplate = new RestTemplate();
        // 连接超时
        ((SimpleClientHttpRequestFactory) restTemplate.getRequestFactory()).setConnectTimeout(5000);
        // 读取超时
        ((SimpleClientHttpRequestFactory) restTemplate.getRequestFactory()).setReadTimeout(10000);
        List<ClientHttpRequestInterceptor> list = new ArrayList<>();
        list.add(new MyRestClientInterceptor());
        restTemplate.setInterceptors(list);
    }

    public Map getForMap(String url) throws ServiceException {
        String result = restTemplate.getForObject(url, String.class);
        return JsonUtil.fromJson(result, Map.class);
    }

    public <T> T getForObject(String url, Class<T> elementType) {
        return restTemplate.getForObject(url, elementType);
    }

    public <T> T getForObject(String url, Class<T> elementType, Object urlVariables) {
        return restTemplate.getForObject(formatGetUrl(url, JsonUtil.convertValue(urlVariables, Map.class)), elementType);
    }

    public <T> T getForObject(String url, Class<T> elementType, Map<String, ?> urlVariables) {
        return restTemplate.getForObject(formatGetUrl(url, urlVariables), elementType);
    }

    @SuppressWarnings("unchecked")
    public <T> List<T> getForList(String url, Class<T> elementType) throws ServiceException {
        String response = restTemplate.getForObject(url, String.class);
        return JsonUtil.fromJson(response, List.class, elementType);
    }

    @SuppressWarnings("unchecked")
    public <T> List<T> getForList(String url, Class<T> elementType, Object urlVariables) throws ServiceException {
        String response = restTemplate.getForObject(formatGetUrl(url, JsonUtil.convertValue(urlVariables, Map.class)), String.class);
        return JsonUtil.fromJson(response, List.class, elementType);
    }

    @SuppressWarnings("unchecked")
    public <T> List<T> getForList(String url, Class<T> elementType, Map<String, ?> urlVariables) throws ServiceException {
        String response = restTemplate.getForObject(formatGetUrl(url, urlVariables), String.class);
        return JsonUtil.fromJson(response, List.class, elementType);
    }

    public String postForObject(String url, Object request) {
        return restTemplate.postForObject(url, JsonUtil.convertValue(request, Map.class), String.class);
    }

    public <T> T postForObject(String url, Object request, Class<T> responseType) {
        return restTemplate.postForObject(url, JsonUtil.convertValue(request, Map.class), responseType);
    }

    //restTemplate实现patch请求
    public <T> T patchForObject(String url, Object request, Class<T> responseType) {
        HttpEntity<Map> requestEntity = new HttpEntity<>(JsonUtil.convertValue(request, Map.class));
        HttpClient httpClient = HttpClients.createDefault();
        restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
        ResponseEntity<T> responseEntity = restTemplate.exchange(url, HttpMethod.PATCH, requestEntity, responseType);
        return responseEntity.getBody();
    }

    public <T> T delete(String url, Class<T> responseType) {
        ResponseEntity<T> responseEntity = restTemplate.exchange(url, HttpMethod.DELETE, null, responseType);
        return responseEntity.getBody();
    }

    private String formatGetUrl(String url, Map map) {
        if (map != null) {
            StringBuilder stringBuilder = new StringBuilder();
            Iterator iterator = map.keySet().iterator();
            if (iterator.hasNext()) {
                stringBuilder.append("?");
                for (; iterator.hasNext(); ) {
                    String key = (String) iterator.next();
                    Object value = map.get(key);
                    if (value != null && !StringUtils.isEmpty(value.toString())) {
                        stringBuilder.append(underscoreName(key)).append("=").append(value).append("&");
                    }
                }
                stringBuilder.deleteCharAt(stringBuilder.length() - 1);
                url += stringBuilder.toString();
            }
        }
        return url;
    }

    private String underscoreName(String name) {
        StringBuilder result = new StringBuilder();
        if (name != null && name.length() > 0) {
            result.append(name.substring(0, 1));
            for (int i = 1; i < name.length(); i++) {
                String s = name.substring(i, i + 1);
                if (s.equals(s.toUpperCase()) && !Character.isDigit(s.charAt(0)) && !"_".equals(s)) {
                    result.append("_");
                }
                result.append(s.toLowerCase());
            }
        }
        return result.toString();
    }

}